package com.java.jwt.filter.utils.filter;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.java.jwt.filter.utils.config.UserGrantedAuthority;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;

/**
 * @author 陈烽
 */
@Slf4j
public class JwtAuthenticationFilter extends BasicAuthenticationFilter {

    //    @Value("${jwt.secret}")
    private String jwtSecret = "test_key";
    private final String BEARER_PREFIX = "Bearer ";

    //    public JwtAuthenticationFilter(AuthenticationManager authenticationManager, String jwtSecret) {
//        super(authenticationManager);
//        this.jwtSecret = jwtSecret;
//    }
    public JwtAuthenticationFilter(AuthenticationManager authenticationManager) {
        super(authenticationManager);
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
        String authorization = request.getHeader("authorization");
        if (authorization == null || !authorization.startsWith(BEARER_PREFIX)) {
            chain.doFilter(request, response);
            return;
        }
        UsernamePasswordAuthenticationToken authenticationToken = getAuthentication(authorization);
        SecurityContextHolder.getContext().setAuthentication(authenticationToken);
        //SecurityContextHolder.getContext().getAuthentication().getPrincipal() 获取存取的内容
        chain.doFilter(request, response);
    }

    private UsernamePasswordAuthenticationToken getAuthentication(String authorization) {
        if (authorization != null) {
            try {
                Algorithm algorithm = Algorithm.HMAC256(jwtSecret);
                JWTVerifier verifier = JWT.require(algorithm)
                        .acceptLeeway(1)
                        .acceptExpiresAt(5)
                        .build();
                DecodedJWT jwt = verifier.verify(authorization.replace(BEARER_PREFIX, ""));
                Map<String, Claim> claims = jwt.getClaims();
                Claim uidClaim = claims.get("uid");
                Claim accessClaim = claims.get("access");
                Collection<GrantedAuthority> authorities = new ArrayList<>();
                GrantedAuthority grantedAuthority = new UserGrantedAuthority(accessClaim.asString());
                authorities.add(grantedAuthority);
                log.info("过滤器搭配成功");
                return new UsernamePasswordAuthenticationToken(uidClaim.asLong(), null, authorities);
            } catch (JWTVerificationException exception) {
                return null;
            }
        }
        return null;
    }

}
